#include "UIContainer.h"
#include "win_gdi.h"
#include "win_nt.h"

UIContainer::UIContainer(UIContainer *parent)
{
    setParent(parent);
}

UIContainer::~UIContainer()
{
}

UIContainer *UIContainer::getRoot()
{
    UIContainer *pRoot = this;
    while (pRoot->m_Parent != nullptr)
    {
        pRoot = pRoot->m_Parent;
    }
    return pRoot;
}

DuiWinManager *UIContainer::getWinManager()
{
    return this->pWinManger;
}

UIContainer *UIContainer::getParent()
{
    return m_Parent;
}

void UIContainer::setParent(UIContainer *parent)
{
    if (this->m_Parent == parent && parent!= nullptr)
        return;

    // 如果已经有父UI，先移除
    if (this->m_Parent != nullptr)
    {
        this->m_Parent->removeChild(this);
    }

    // 同时更新当前UI和父UI关系
    this->m_Parent = parent;
    if (parent != nullptr)
        parent->addChild(this);
}

void UIContainer::addChild(UIContainer *child)
{
    this->children.push_back(child);
}

void UIContainer::removeChild(UIContainer *child)
{
    for (int i = 0; i < this->children.size(); i++)
    {
        if (this->children[i] == child)
        {
            this->children.erase(this->children.begin() + i);
            break;
        }
    }
}

int UIContainer::getChildCount()
{
    return this->children.size();
}

UIContainer *UIContainer::getChild(int index)
{
    if (index >= 0 && index < this->children.size())
    {
        return this->children[index];
    }
    return nullptr;
}

int UIContainer::getChildIndex(UIContainer *child)
{
    for (int i = 0; i < this->children.size(); i++)
    {
        if (this->children[i] == child)
        {
            return i;
        }
    }
    return -1;
}

void UIContainer::setText(const std::string &val)
{
    this->m_Text = val;
    // UTF8 转 UTF16
    wchar_t buf[1024*10] = {0};
    int len = MultiByteToWideChar(CP_UTF8, 0, val.c_str(), val.length(), buf, sizeof(buf));
    this->m_TextW.assign(buf, len);
}

std::string &UIContainer::getText()
{
    char buff[1024*10] = {0};
    int len = WideCharToMultiByte(CP_UTF8, 0, this->m_TextW.c_str(), this->m_TextW.length(), buff, sizeof(buff), NULL, NULL);
    this->m_Text.assign(buff, len);
    return this->m_Text;
}

void UIContainer::setSize(int w, int h)
{
    this->m_Rect.w = w;
    this->m_Rect.h = h;
}

void UIContainer::setPos(int x, int y)
{
    this->m_Rect.x = x;
    this->m_Rect.y = y;
}

bool UIContainer::isHovering()
{
    auto mgr = this->getWinManager();
    // 排除根节点
    if (mgr != nullptr && mgr->pCurHoverUI != nullptr && mgr->pCurHoverUI != mgr->pRoot)
    {
        return mgr->pCurHoverUI == this;
    }
    return false;
}

bool UIContainer::isFocusing()
{
    auto mgr = this->getWinManager();
    // 排除根节点
    if (mgr != nullptr && mgr->pCurFocusUI != nullptr && mgr->pCurFocusUI != mgr->pRoot)
    {
        return mgr->pCurFocusUI == this;
    }
    return false;
}

bool UIContainer::isInContainer(int x, int y)
{
    return x >= this->m_Rect.x && x <= this->m_Rect.x + this->m_Rect.w && y >= this->m_Rect.y &&
           y <= this->m_Rect.y + this->m_Rect.h;
}

void UIContainer::onDraw(DuiWinManager *mgr)
{
    
    // cache mgr
    if (this->pWinManger == nullptr)
        this->pWinManger = mgr;

    auto isHovering = this->isHovering();
    auto isFocused = this->isFocusing();

    // m_Rect
    // https://developer.mozilla.org/zh-CN/docs/Learn/CSS/Building_blocks/The_box_model#%E4%BB%80%E4%B9%88%E6%98%AF_css_%E7%9B%92%E6%A8%A1%E5%9E%8B%EF%BC%9F
    auto rect_out = DuiRect{
        this->m_Rect.x + this->m_Margin.r,
        this->m_Rect.y + this->m_Margin.t,
        this->m_Rect.w - this->m_Margin.l - this->m_Margin.r,
        this->m_Rect.h - this->m_Margin.t - this->m_Margin.b,
    };
    auto rect_in = DuiRect{
        rect_out.x + this->m_Padding.l,
        rect_out.y + this->m_Padding.t,
        rect_out.w - this->m_Padding.l - this->m_Padding.r,
        rect_out.h - this->m_Padding.t - this->m_Padding.b,
    };
    // background
    render_draw_fill(mgr, rect_out, this->m_BackgroundColor, this->m_BorderRadius);
    // if (isFocused)
        // render_draw_fill(mgr, rect_out, DuiColor{0, 0, 255, 100}, this->m_BorderRadius);
    if (isHovering)
        render_draw_fill(mgr, rect_out, DuiColor{0, 255, 0, 100}, this->m_BorderRadius);
    if (this->m_BackgroundImage.length() > 0)
        render_draw_image(mgr, rect_out, this->m_BackgroundImage);

    // shadow
    if (this->m_ShadowOffset.x != 0 || this->m_ShadowOffset.y != 0)
        render_draw_shadow(mgr, rect_out, this->m_ShadowOffset, this->m_BorderRadius, this->m_ShadowColor);

    // border or border image
    if (this->m_BorderWidth > 0)
        render_draw_rect(mgr, rect_out, this->m_BorderColor, this->m_BorderWidth, this->m_BorderLineStyle,
                         this->m_BorderRadius);
    if (this->m_BorderImage.length() > 0)
        render_draw_border_image(mgr, rect_out, this->m_BorderImageCorner, this->m_BorderImage, DuiColor{0, 0, 0, 0});

    // content
    this->onDrawContent(mgr, rect_in, rect_out);
}

DuiPoint UIContainer::getMousePos()
{
    return m_mousePos;
}

void UIContainer::onMouseDown(int x, int y)
{
}

void UIContainer::onMouseUp(int x, int y)
{
}

void UIContainer::onMouseMove(int x, int y)
{
    m_mousePos.x = x;
    m_mousePos.y = y;
}

void UIContainer::onMouseLeave()
{
    if(this->m_Cursor != DUI_CURSOR_STYLE_ARROW) {
        shell_win_set_cursor(DUI_CURSOR_STYLE_ARROW);
    }
}

void UIContainer::onMouseEnter()
{
    if(this->m_Cursor != DUI_CURSOR_STYLE_ARROW) {
        shell_win_set_cursor(this->m_Cursor);
    }
}

void UIContainer::onMouseWheel(int delta, int x, int y)
{
}

void UIContainer::onKeyDown(int key)
{
}

void UIContainer::onKeyUp(int key)
{
}

void UIContainer::onKeyChar(int key)
{
}

void UIContainer::onImeChar(int key)
{
}

void UIContainer::onCommand(int command, void *param)
{
}
